<script setup>
import { Codemirror } from 'vue-codemirror'
import { json } from '@codemirror/lang-json'
import { oneDark } from '@codemirror/theme-one-dark'
import useClipboard from 'vue-clipboard3'
import html2canvas from 'html2canvas'
import { printHtml } from '@/utils'
import { useTemplateStore } from '@/stores'
import { nanoid } from 'nanoid'
import { cloneDeep } from 'lodash-es'

const componentRef = useTemplateRef('componentRef')

// json出错提示
const jsonParseErr = ref('')
// 编辑的json
const editCode = ref({})
const handleCodeChange = str => {
  try {
    editCode.value = JSON.parse(str)
    jsonParseErr.value = ''
  } catch (err) {
    str && (jsonParseErr.value = err.message)
  }
}

// 查看schema
const codeStr = ref('')
const codeVisible = ref(false)
const handleCode = () => {
  const _schema = componentRef.value?.schema ?? {}
  editCode.value = cloneDeep(_schema)
  codeStr.value = JSON.stringify(_schema, null, 2)
  codeVisible.value = true
}
const handleCodeCancel = () => {
  codeStr.value = ''
  jsonParseErr.value = ''
  codeVisible.value = false
}
const { toClipboard } = useClipboard()
const handleCopy = async () => {
  await toClipboard(codeStr.value)
  ElMessage.success({ grouping: true, plain: true, message: '已复制' })
}

// 储存模板
const templateStore = useTemplateStore()
const { handleSaveTemplateToLocal, handleUpdateCurrentSchema } = templateStore
const handleSaveLocal = () => {
  const _schema = componentRef.value?.schema
  handleSaveTemplateToLocal(_schema)
}
const handleUpdate = () => {
  // componentRef.value?.updateSchema(editCode.value)
  handleUpdateCurrentSchema(editCode.value)
  ElMessage.success({ grouping: true, plain: true, message: '已更新' })
}

// 预览打印
const previewVisible = ref(false)
const htmlStr = ref('')
const handlePreview = async () => {
  const _html = await componentRef.value?.getHtml()
  htmlStr.value = _html.replace(/activeClass/g, 'borderSolidClass')
  previewVisible.value = true
}
const handlePrint = () => {
  printHtml(htmlStr.value)
  previewVisible.value = false
}

const isLoading = ref(false)
const handleDownload = async () => {
  isLoading.value = true
  await nextTick()
  const cavs = await html2canvas(document.querySelector('#preview-contanier'))
  const link = document.createElement('a')
  link.href = cavs.toDataURL()
  const name = (editCode.value?.name || '打印') + `-${nanoid(8)}.png`
  link.download = name
  link.click()
  await nextTick()
  isLoading.value = false
  ElMessage.success({ grouping: true, plain: true, message: '已下载' })
}

const extensions = [json(), oneDark]
</script>

<template>
  <el-config-provider size="small">
    <el-container class="h-full">
      <el-header>
        <section class="flex flex-justify-between flex-items-center">
          <el-menu
            default-active="/"
            mode="horizontal"
            router
            class="flex-1"
          >
            <el-menu-item index="/">
              <el-icon><List /></el-icon>
              表单设计器
            </el-menu-item>
            <el-menu-item index="/table">
              <el-icon><Grid /></el-icon>
              表格设计器
            </el-menu-item>
          </el-menu>
          <section>
            <el-button
              type="primary"
              icon="Download"
              @click="handleSaveLocal"
              plain
              >保存模板</el-button
            >
            <el-button
              type="primary"
              icon="View"
              @click="handleCode"
              >查看 Schema</el-button
            >
            <el-button
              type="success"
              icon="Printer"
              @click="handlePreview"
              >预览下载打印</el-button
            >
          </section>
        </section>
      </el-header>
      <el-main class="p-0">
        <RouterView v-slot="{ Component }">
          <KeepAlive>
            <component
              :is="Component"
              ref="componentRef"
            />
          </KeepAlive>
        </RouterView>
      </el-main>

      <el-drawer
        @close="handleCodeCancel"
        v-model="codeVisible"
        title="Schema Code"
      >
        <el-alert
          v-if="jsonParseErr"
          title="JSON parse Error"
          type="error"
          :description="jsonParseErr"
          show-icon
        />
        <el-scrollbar max-height="100%">
          <Codemirror
            v-model="codeStr"
            :extensions="extensions"
            :tab-size="2"
            indent-with-tab
            @change="handleCodeChange"
          />
        </el-scrollbar>
        <template #footer>
          <div>
            <el-button @click="codeVisible = false">Cancel</el-button>
            <el-button
              @click="handleUpdate"
              type="success"
              :disabled="!!jsonParseErr"
              >Update</el-button
            >
            <el-button
              @click="handleCopy"
              type="primary"
              :disabled="!!jsonParseErr"
              >Copy</el-button
            >
          </div>
        </template>
      </el-drawer>

      <el-dialog
        v-model="previewVisible"
        title="Preview"
        align-center
        width="auto"
      >
        <el-scrollbar max-height="600">
          <div
            id="preview-contanier"
            v-html="htmlStr"
            class="w-[210mm] h-[297mm]"
          ></div>
        </el-scrollbar>
        <template #footer>
          <div>
            <el-button @click="previewVisible = false">Cancel</el-button>
            <el-button
              type="success"
              :loading="isLoading"
              @click="handleDownload"
              >Download</el-button
            >
            <el-button
              type="primary"
              @click="handlePrint"
              >Print</el-button
            >
          </div>
        </template>
      </el-dialog>
    </el-container>
  </el-config-provider>
</template>
